package com.atwisdom.star.core.bsl.modelClass.logic.Impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.atwisdom.star.common.actionType.modelClass.logic.LogicActionType;
import com.atwisdom.star.common.util.ExpressionUtil;
import com.atwisdom.star.common.util.JsonUtil;
import com.atwisdom.star.common.vo.*;
import com.atwisdom.star.core.bsl.functionClass.CalculateService;
import com.atwisdom.star.core.bsl.modelClass.logic.LogicInstanceBslService;
import com.atwisdom.star.core.dao.pojo.modelClass.hier.HierInstance;
import com.atwisdom.star.core.dao.pojo.modelClass.logic.LogicInstance;
import com.atwisdom.star.core.dsl.functionClass.BatchNumberDslService;
import com.atwisdom.star.core.dsl.modelClass.consume.Impl.ConsumeInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.hier.HierInstanceDslService;
import com.atwisdom.star.core.dsl.modelClass.logic.Impl.LogicInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.logic.Impl.LogicModelDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.resource.Impl.ResourceInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.tank.Impl.TankInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.utils.QueryBuilder;
import com.atwisdom.star.exception.pojo.BusinessException;
import com.googlecode.aviator.AviatorEvaluator;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
@Slf4j
@AllArgsConstructor
public class LogicInstanceBslServiceImpl implements LogicInstanceBslService, CalculateService {
    private LogicModelDslServiceImpl logicModelDslService;
    private LogicInstanceDslServiceImpl logicInstanceDslService;
    private ConsumeInstanceDslServiceImpl consumeInstanceDslService;
    private ResourceInstanceDslServiceImpl resourceInstanceDslService;
    private TankInstanceDslServiceImpl tankInstanceDslService;
    private HierInstanceDslService hierInstanceDslService;
    private QueryBuilder queryBuilder;
    private BatchNumberDslService batchNumberDslService;


    /**
     * 服务工厂方法
     *
     * @param actionDataList 参数
     * @return 参数
     * @throws BusinessException 异常
     */
    @Transactional
    public ResultInfo<?> responseFactory(List<ActionData<JSONObject>> actionDataList) throws BusinessException {
        ResultInfo<?> resultInfo = null;
        for (ActionData<JSONObject> actionData : actionDataList) {
            String action = actionData.getAction();
            LogicActionType actionType = LogicActionType.valueOf(action);
            String methodName = actionType.getMethodName();
            resultInfo = this.execMethod(methodName, actionData);
        }
        return resultInfo;
    }

    /**
     * 反射执行业务单元方法
     *
     * @param methodName 方法名
     * @param actionData 方法参数
     * @return 返回结果
     * @throws BusinessException 业务异常
     */
    public ResultInfo<?> execMethod(String methodName, ActionData<JSONObject> actionData) throws BusinessException {
        Class<? extends LogicInstanceBslServiceImpl> clz = this.getClass();
        try {
            Method method = clz.getMethod(methodName, ActionData.class);
            LogicInstanceBslServiceImpl service = (LogicInstanceBslServiceImpl) AopContext.currentProxy();
            return (ResultInfo<?>) method.invoke(service, actionData);
        } catch (NoSuchMethodException ex) {
            throw new BusinessException("999999", "没有找到该方法(" + methodName + ")", ex);
        } catch (IllegalAccessException ex) {
            throw new BusinessException("999999", "没有访问该方法权限(" + methodName + ")", ex);
        } catch (InvocationTargetException ex) {
            Throwable targetException = ex.getTargetException();
            if (targetException instanceof BusinessException) {
                BusinessException bex = (BusinessException) targetException;
                throw new BusinessException("999999", bex.getErrorMsg(), ex);
            } else {
                throw new BusinessException("999999", "出错了请重试：(" + methodName + ")---" + ex.getTargetException().getMessage(), ex.getTargetException());
            }
        }
    }

    /**
     * 查询全部摘要（通用）
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> queryAllInfo(ActionData<JSONObject> actionData) {
        List<JSONObject> jsonObjectList = this.logicInstanceDslService.queryAllInfo();
        return JsonResult.success(jsonObjectList);
    }

    /**
     * 分页查询全部摘要（通用）
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<PageInfo> queryAllInfoByPage(ActionData<JSONObject> actionData) {
        int pageNumber = actionData.getPageNumber();
        int pageSize = actionData.getPageSize();
        String orderBy = actionData.getOrderBy();
        PageInfo pageInfo = this.logicInstanceDslService.queryAllInfoByPage(pageNumber, pageSize, orderBy, actionData.isNeedHier());
        return JsonResult.success(pageInfo);
    }

    /**
     * 查询全部数据（通用）
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> queryAll(ActionData<JSONObject> actionData) {
        List<JSONObject> jsonObjectList = this.logicInstanceDslService.queryAll();
        return JsonResult.success(jsonObjectList);
    }

    /**
     * 分页查询全部数据（通用）
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> listAllByPage(ActionData<JSONObject> actionData) {
        int pageNumber = actionData.getPageNumber();
        int pageSize = actionData.getPageSize();
        String orderBy = actionData.getOrderBy();
        PageInfo pageInfo = this.logicInstanceDslService.listAllByPage(pageNumber, pageSize, orderBy, actionData.isNeedHier());
        return JsonResult.success(pageInfo);
    }

    /**
     * 按条件查询模型
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> query(ActionData<JSONObject> actionData) {
        List<JSONObject> queryJsonList;
        boolean hiddenHierData = actionData.isHiddenHierData();
        if (hiddenHierData) {
            queryJsonList = this.logicInstanceDslService.queryWithoutHier(actionData.getCondition(), actionData.getClassName(), actionData.getOrderBy());
        } else {
            queryJsonList = queryJson(actionData);
        }

        return JsonResult.success(queryJsonList);
    }

    // /**
    //  * 按条件查询，并汇总数据
    //  *
    //  * @param actionData 参数
    //  * @return 返回值
    //  */
    // @Override
    // public ResultInfo<?> queryAndCalculate(ActionData<JSONObject> actionData) {
    //     List<JSONObject> queryJsonList = queryJson(actionData);
    //     String statisticsExpression = actionData.getStatisticsExpression();
    //     HashMap<String, Object> calculateParamMap = new HashMap<>();
    //     Map<String, String> jsonPathMap = actionData.getStatisticsJsonPathMap();
    //     jsonPathMap.forEach((paramName, jsonPath) -> {
    //         Object result = JsonPath.read(queryJsonList, jsonPath);
    //         calculateParamMap.put(paramName, result);
    //         // OptionalDouble average = Arrays.stream(result.toArray(new Double[doubleList.size()])).mapToDouble(Number::doubleValue).average();
    //         // System.out.println("average："+average);
    //     });
    //     Expression expression = AviatorEvaluator.compile(statisticsExpression, true);
    //     Object result = expression.execute(calculateParamMap);
    //     return JsonResult.success(result);
    // }

    /**
     * 按条件查询，并按指定字段合并分组后，计算指定字段的总和
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> queryAndSum(ActionData<JSONObject> actionData) {
        List<JSONObject> queryJsonList = queryJson(actionData);
        String groupKey = actionData.getGroupKey();
        String sumKey = actionData.getSumKey();
        Map<Object, BigDecimal> sumMap = queryJsonList.stream()
                .collect(Collectors.groupingBy(d -> d.getJSONObject("values").get(groupKey),
                        Collectors.reducing(BigDecimal.ZERO, obj -> obj.getJSONObject("values").getBigDecimal(sumKey), BigDecimal::add)));
        List<JSONObject> resultList = new ArrayList<>();
        sumMap.forEach((k, v) -> {
            JSONObject result = new JSONObject();
            result.put(groupKey, k);
            result.put(sumKey, v);
            resultList.add(result);
        });
        return JsonResult.success(resultList);
    }


    /**
     * 查询实例容器hier
     *
     * @param actionData 参数
     * @return 返回hier
     */
    public ResultInfo<?> queryHierById(ActionData<JSONObject> actionData) {
        Long id = actionData.getId();
        JSONObject jsonObject = this.logicInstanceDslService.queryHierById(id);
        return JsonResult.success(jsonObject);
    }

    /**
     * 按条件分页查询模型实例摘要
     *
     * @param actionData 参数
     * @return 返回结果
     */
    public ResultInfo<?> queryInfoByPage(ActionData<JSONObject> actionData) {
        int pageNumber = actionData.getPageNumber();
        int pageSize = actionData.getPageSize();
        String condition = actionData.getCondition();
        String className = actionData.getClassName();
        String orderBy = actionData.getOrderBy();
        PageInfo pageInfo = this.logicInstanceDslService.queryInfoByPage(pageNumber, pageSize, condition, className, orderBy, actionData.isNeedHier());
        return JsonResult.success(pageInfo);
    }

    /**
     * 按条件分页查询模型实例
     *
     * @param actionData 参数
     * @return 返回结果
     */
    public ResultInfo<?> queryByPage(ActionData<JSONObject> actionData) {
        int pageNumber = actionData.getPageNumber();
        int pageSize = actionData.getPageSize();
        String condition = actionData.getCondition();
        String className = actionData.getClassName();
        String orderBy = actionData.getOrderBy();
        boolean hiddenHierData = actionData.isHiddenHierData();
        PageInfo pageInfo;
        if (hiddenHierData) {
            pageInfo = this.logicInstanceDslService.queryByPageWithoutHier(pageNumber, pageSize, condition, className, orderBy);
        } else {
            String hierValueCondition = actionData.getHierValueCondition();
            pageInfo = this.logicInstanceDslService.queryByPage(pageNumber, pageSize, condition, className, orderBy, hierValueCondition);
        }

        return JsonResult.success(pageInfo);
    }

    /**
     * 初始化工艺路线实例
     *
     * @param actionData 参数
     * @return 反回工艺路线实例json
     */
//    @LogicInstanceAnnotation
    @Override
    public ResultInfo<?> add(ActionData<JSONObject> actionData) {
        List<JSONObject> data = actionData.getData();
        JSONObject jsonObject = data.get(0);
        JSONObject initialJson = addJson(jsonObject);
        return JsonResult.success(initialJson);
    }

    /**
     * 保存实例
     *
     * @param actionData 参数
     * @return 反回工艺路线实例json
     */
    @Override
    public ResultInfo<?> saveOrUpdate(ActionData<JSONObject> actionData) {
        List<JSONObject> data = actionData.getData();
        JSONObject dataJson = data.get(0);
        if (dataJson.getLong("id") != null) {
            return updateById(actionData);
        } else {
            return add(actionData);
        }
    }

    /**
     * 指增加数据
     *
     * @param actionData
     * @return
     */
    public ResultInfo<?> batchAddWithHier(ActionData<JSONObject> actionData) {
        List<JSONObject> resultList = new ArrayList<>();
        for (JSONObject data : actionData.getData()) {
            JSONObject initialJson = addJson(data);
            JSONArray hierArray = data.getJSONArray("hierArray");
            for (int i = 0; i < hierArray.size(); i++) {
                JSONObject hierJson = hierArray.getJSONObject(i);
                hierJson.put("containerId", initialJson.get("id"));
                hierJson.put("containerModel", "logic");
                hierInstanceDslService.addChild(hierJson);
            }
            resultList.add(initialJson);
        }
        return JsonResult.success(resultList);
    }

    /**
     * 指增加数据
     *
     * @param actionData
     * @return
     */
    public ResultInfo<?> batchAdd(ActionData<JSONObject> actionData) {
        List<JSONObject> resultList = new ArrayList<>();
        for (JSONObject jsonObject : actionData.getData()) {
            JSONObject initialJson = addJson(jsonObject);
            resultList.add(initialJson);
        }
        return JsonResult.success(resultList);
    }

    private JSONObject addJson(JSONObject jsonObject) {
        String type = jsonObject.getString("type");
        String className = jsonObject.getString("className");
        String name = jsonObject.getString("name");
        JSONObject values = jsonObject.getJSONObject("values");
        return logicInstanceDslService.add(type, className, name, values);
    }

    /**
     * 更新模型属性字段
     * 更新，需要同步更新实例，同步更新历史数据
     * 1、className 和 自定字段
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
//    @LogicInstanceAnnotation
    public ResultInfo<?> updateById(ActionData<JSONObject> actionData) {
        List<JSONObject> data = actionData.getData();
        List<JSONObject> upJsonList = new ArrayList<>();
        for (JSONObject updateJson : data) {
            boolean updateNullFlag = actionData.isUpdateNullFlag();
            if (updateNullFlag) {
                this.logicInstanceDslService.updateFieldNullById(updateJson);
            }
            JSONObject jsonObject = this.logicInstanceDslService.updateById(updateJson);
            upJsonList.add(jsonObject);
        }
        if(upJsonList.size()>0){
            return JsonResult.success(upJsonList);
        }else{
            return JsonResult.success(upJsonList.get(0));
        }
    }

    /**
     * 更新
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> updateByCondition(ActionData<JSONObject> actionData) {
        List<JSONObject> data = actionData.getData();
        List<JSONObject> resultList = logicInstanceDslService.updateByCondition(actionData.getClassName(), actionData.getCondition(), JsonUtil.toJSONObject(data.get(0)));
        return JsonResult.success(resultList);
    }

    /**
     * 扫条件删除数据
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> deleteByCondition(ActionData<JSONObject> actionData) {
        logicInstanceDslService.deleteByCondition(actionData.getClassName(), actionData.getCondition());
        return JsonResult.success();
    }

    /**
     * 更新实例hier
     *
     * @param actionData 更新参数
     * @return 返回更新的实例
     */
    public ResultInfo<?> updateHier(ActionData<JSONObject> actionData) {
        List<JSONObject> data = actionData.getData();
        JSONObject jsonObject = data.get(0);
        Long id = jsonObject.getLong("id");
        String className = jsonObject.getString("className");
        JSONObject hier = jsonObject.getJSONObject("hier");
        JSONObject hierProperties = this.logicModelDslService.queryHierProperties(className);

        JSONObject hierJson = queryBuilder.fetchHierBy(hierProperties, hier);
        dealHierLinkInstance(hierJson);
        LogicInstance logicInstance = this.logicInstanceDslService.queryById(id);
        //更新hier实例
        hierJson.put("containerId", logicInstance.getId());
        hierJson.put("containerModel", ModelType.Logic.getCode());
        this.hierInstanceDslService.updateByContainerId(ModelType.Logic.getCode(), className, logicInstance.getId(), hierJson);
        JSONObject infoJsonObject = logicInstance.getInfoJsonObject();
        JSONObject resultJsonObject = logicInstanceDslService.updateById(infoJsonObject);
        return JsonResult.success(resultJsonObject);
    }

    /**
     * 处理hierLink
     *
     * @param hier 参数
     */
    private void dealHierLinkInstance(JSONObject hier) {
        JSONArray tempContent = hier.getJSONArray("content");
        JSONArray content = new JSONArray();
        for (int i = 0; i < tempContent.size(); i++) {
            JSONObject contentJson = tempContent.getJSONObject(i);
            JSONObject link = contentJson.getJSONObject("link");
            this.createInstance(link);
            contentJson.put("link", link);
            content.add(contentJson);
        }
        hier.put("content", content);
    }


    /**
     * 根据link 创建实例
     *
     * @param link 创建实例参数
     */
    private void createInstance(JSONObject link) {
        if (link == null) {
            return;
        }

        String id = link.getString("id");
        if (StringUtils.isNotBlank(id)) {
            return;
        }
        JSONObject values = link.getJSONObject("values");
        if (values == null || values.size() < 1) {
            return;
        }
        String type = link.getString("type");
        String className = link.getString("className");
        if (StringUtils.isBlank(type) || StringUtils.isBlank(className)) {
            return;
        }

        ModelType modelType = ModelType.getByCode(type);
        JSONObject jsonObject;
        switch (modelType) {
            case Consume:
                jsonObject = consumeInstanceDslService.add(type, className, className, values);
                link.put("id", jsonObject.getString("id"));
                break;
            case Resource:
                jsonObject = resourceInstanceDslService.add(type, className, className, values);
                link.put("id", jsonObject.getString("id"));
                break;
            case Logic:
                jsonObject = logicInstanceDslService.add(type, className, className, values);
                link.put("id", jsonObject.getString("id"));
                break;
            case Tank:
                jsonObject = this.tankInstanceDslService.add(type, className, className, values);
                link.put("id", jsonObject.getString("id"));
                break;
            default:
                break;
        }
    }

    /**
     * 更新模型属性字段
     * 更新，需要同步更新实例，同步更新历史数据
     * 1、className 和 自定字段
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> updateByIds(ActionData<JSONObject> actionData) {
        List<JSONObject> jsonObjectList = this.logicInstanceDslService.updateByIds(actionData.getData());
        return JsonResult.success(jsonObjectList);
    }

    @Override
    public ResultInfo<?> updateByBatchId(ActionData<JSONObject> actionData) {
        List<JSONObject> dataList = actionData.getData();
        JSONObject data = dataList.get(0);
        List<JSONObject> result = logicInstanceDslService.updateByBatchId(data);
        return JsonResult.success(result);
    }

    /**
     * 更新模型类型和类名（配置阶段）
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> updateClassName(ActionData<JSONObject> actionData) {
        List<JSONObject> data = actionData.getData();
        List<JSONObject> jsonObjectList = this.logicInstanceDslService.updateClassName(data.get(0));
        return JsonResult.success(jsonObjectList);
    }

    /**
     * 按ids删除模型
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> deleteByIds(ActionData<JSONObject> actionData) {
        List<Long> ids = actionData.getIds();
        this.logicInstanceDslService.deleteByIds(ids);
        return JsonResult.success(StatusCode.SUCCESS);
    }

    /**
     * 接className删除
     * 1、删除实例、2、删除历史 3、更新redis
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> deleteByClassName(ActionData<JSONObject> actionData) {
        String className = actionData.getClassName();
        this.logicInstanceDslService.deleteByClassName(className);
        return JsonResult.success(StatusCode.SUCCESS);
    }

    /**
     * 批量删除
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> deleteByClassNames(ActionData<JSONObject> actionData) {
        List<String> classNames = actionData.getClassNames();
        this.logicInstanceDslService.deleteByClassNames(classNames);
        return JsonResult.success(StatusCode.SUCCESS);
    }

    /**
     * 按Id 废除模型
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> repealByIds(ActionData<JSONObject> actionData) {
        List<Long> ids = actionData.getIds();
        this.logicInstanceDslService.repealByIds(ids);
        return JsonResult.success(StatusCode.SUCCESS);
    }

    /**
     * 批量废除
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> repealByClassNames(ActionData<JSONObject> actionData) {
        List<String> classNames = actionData.getClassNames();
        this.logicInstanceDslService.repealByClassNames(classNames);
        return JsonResult.success(StatusCode.SUCCESS);
    }

    /**
     * 按指定主表记录的Hier记录分组，并生成下游单据，要求下游单据的Hier与上游单据Hier的属性一致
     * 目前只有主表字段映射，后期如果有需要，可以增加hier字段映射关系
     *
     * @param actionData
     * @return
     */
    @Override
    public ResultInfo<?> splitByGroupKey(ActionData<JSONObject> actionData) {
        String model = actionData.getModel();
        Long containerId = actionData.getInstanceId();
        String groupByKey = actionData.getGroupKey();
        String parentNodeId = actionData.getParentId();

        // 查询主表记录
        JSONObject logicInstanceJson = logicInstanceDslService.queryJsonById(containerId);
        Map<Object, List<HierInstance>> resultMap = hierInstanceDslService.fetchByParentNodeIdAndGroupBy(model, containerId, parentNodeId, groupByKey);
        // 根据上面的查询可以得出，需要分解成3条新记录，如何创建新的实例呢？ 新的主表记录的model, className, 字段映射关系
        List<JSONObject> resultJsonList = new ArrayList<>();
        resultMap.forEach((k, v) -> {
            JSONObject resultJson = new JSONObject();
            resultJson.put("master", logicInstanceJson);
            resultJson.put("slave", v);
            resultJsonList.add(resultJson);
        });
        JSONObject dataJson = actionData.getData().get(0);
        JSONObject targetJson = dataJson.getJSONObject("target");
        List propertyMapList = dataJson.getJSONArray("propertyMapList");
        copy1(resultJsonList, targetJson, propertyMapList);

        return JsonResult.success(resultJsonList);
    }

    /**
     * 把指定数据复制到另一个className中
     *
     * @param sourceList      源数据
     * @param targetJson      新的数据值，执行中会覆盖源数据
     * @param propertyMapList 字段映射关系
     */
    @Override
    public List<JSONObject> copy1(List<JSONObject> sourceList, JSONObject targetJson, List<String> propertyMapList) {
        // 先生成主表记录，要用到源主表记录的指定字段，及子表记录的第一条记录
        List<JSONObject> targetList = new ArrayList<>();
        for (int i = 0; i < sourceList.size(); i++) {
            JSONObject tempTargetJson = ObjectUtil.cloneByStream(targetJson);
            JSONObject source = sourceList.get(i);
            JSONObject master = source.getJSONObject("master");
            // JSONObject sourceValueJson = master.getJSONObject("values");
            JSONArray slaveArray = source.getJSONArray("slave");
            JSONObject firstSlave = CollectionUtil.isNotEmpty(slaveArray) ? slaveArray.getJSONObject(0) : null;
            // JSONObject firstSlaveValueJson = firstSlave.getJSONObject("values");
            String type = tempTargetJson.getString("type");
            String className = tempTargetJson.getString("className");
            String parentId = tempTargetJson.getString("parentId");
            String name = tempTargetJson.getString("name");
            JSONObject targetValueJson = tempTargetJson.getJSONObject("values");
            handlePropertyMap(propertyMapList, master, firstSlave, targetValueJson);
            logicInstanceDslService.handleAutoGenValue(targetValueJson);
            // 保存主表记录
            JSONObject initialJson = logicInstanceDslService.add(type, className, name, targetValueJson);
            Long containerId = initialJson.getLong("id");
            master.put("id", containerId);
            JSONObject masterObj = new JSONObject();
            masterObj.put("master", initialJson);
            // 生成子表记录
            List<JSONObject> slaveList = createHierList(propertyMapList, tempTargetJson, master, slaveArray);
            masterObj.put("slave", slaveList);
            targetList.add(masterObj);
        }
        return targetList;
    }


    /**
     * 获取物料数据
     *
     * @return
     */
    private Map<String, JSONObject> fetchAllMaterial(List<String> materialBcodeList) {
        if(CollectionUtil.isEmpty(materialBcodeList)){
            return new HashMap<>();
        }

        String inCondition = String.join(",", materialBcodeList.stream()
                .map(id -> "'" + id + "'")
                .collect(Collectors.toList()));
        String className = "material";
        String condition = " bcode in ("+inCondition+")";
        List<JSONObject> dataList = consumeInstanceDslService.query(condition, className, null);
        Map<String, JSONObject> materialMap = dataList.stream().collect(Collectors.toMap(d -> d.getJSONObject("values").getString("bcode"),
                d -> d.getJSONObject("values")));
        return materialMap;
    }

    /**
     * 复制生成子表数据
     *
     * @param propertyMapList
     * @param tempTargetJson
     * @param master
     * @param slaveArray
     * @return
     */
    private List<JSONObject> createHierList(List<String> propertyMapList, JSONObject tempTargetJson, JSONObject master, JSONArray slaveArray) {
        String type = tempTargetJson.getString("type");
        String className = tempTargetJson.getString("className");
        String parentId = tempTargetJson.getString("parentId");
        String name = tempTargetJson.getString("name");
        Long containerId = master.getLong("id");
        JSONObject targetValueJson = tempTargetJson.getJSONObject("values");
        JSONObject targetHierValueJson = tempTargetJson.getJSONObject("hierValues");
        if (targetHierValueJson == null) {
            targetHierValueJson = new JSONObject();
        }
        List<JSONObject> slaveList = new ArrayList<>();
        for (int j = 0; slaveArray != null && j < slaveArray.size(); j++) {
            JSONObject slave = slaveArray.getJSONObject(j);
            // JSONObject slaveValueJson = slave.getJSONObject("values");
            // handleSlavePropertyMap(propertyMap, master, sourceValueJson, targetHierValueJson, slave, slaveValueJson);
            handleSlavePropertyMap(propertyMapList, master, slave, targetHierValueJson);
            slave.put("id", null);
            slave.put("className", className);
            slave.put("containerId", containerId);
            slave.put("parentId", parentId);
            JSONObject newValues = new JSONObject();
            JSONObject originHierValues = slave.getJSONObject("values");

            for (String key : originHierValues.keySet()) {
                if (key.startsWith("warehouse") || key.startsWith("bin") || key.startsWith("material")
                        || key.equals("priceNonTax") || key.equals("price") || key.equals("moneyNonTax")
                        || key.equals("money") || key.equals("taxRate")) {
                    newValues.put(key, originHierValues.get(key));
                }
            }
            List<String> materialBcodeList = new ArrayList<>();
            if(StringUtils.isNotBlank(originHierValues.getString("material_bcode"))){
                materialBcodeList.add(originHierValues.getString("material_bcode"));
            }

            Map<String, JSONObject> materialMap = fetchAllMaterial(materialBcodeList);
            // 将物料信息重新赋值
            for (String key : targetHierValueJson.keySet()) {
                if (key.startsWith("material_")) {
                    String materialKey = key.substring("material_".length());
                    String materialBcode = originHierValues.getString("material_bcode");
                    JSONObject materialValueJson = materialMap.get(materialBcode);
                    targetHierValueJson.put(key, materialValueJson.get(materialKey));
                }
            }

            BeanUtil.copyProperties(targetHierValueJson, newValues);
            slave.put("values", newValues);
            HierInstance hierInstance = hierInstanceDslService.addChild(slave);
            JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(hierInstance));
            slaveList.add(jsonObject);
        }
        return slaveList;
    }

    /**
     * 处理子表的propertyMap数据
     *
     * @param propertyMap
     * @param master
     * @param sourceValueJson
     * @param targetHierValueJson
     * @param slave
     * @param slaveValueJson
     */
    private void handleSlavePropertyMap(Map<String, String> propertyMap, JSONObject master, JSONObject sourceValueJson, JSONObject targetHierValueJson, JSONObject slave, JSONObject slaveValueJson) {
        propertyMap.forEach((sourceKey, targetKey) -> {
            Object tempNewValue;
            if (targetKey.startsWith("slave.")) {
                if (sourceKey.startsWith("slave.values.")) {
                    sourceKey = sourceKey.substring("slave.values.".length());
                    tempNewValue = slaveValueJson.get(sourceKey);
                } else if (sourceKey.startsWith("slave")) {
                    sourceKey = sourceKey.substring("slave.".length());
                    tempNewValue = slave.get(sourceKey);
                } else if (sourceKey.startsWith("master.")) {
                    sourceKey = sourceKey.substring("master.".length());
                    tempNewValue = master.get(sourceKey);
                } else {
                    tempNewValue = sourceValueJson.get(sourceKey);
                }
                targetKey = targetKey.substring("slave.".length());
                targetHierValueJson.put(targetKey, tempNewValue);
            }
        });
    }


    /**
     * 复制指定节点的Hier数据，并按指定的字段进行数量拆分
     *
     * @param actionData
     */
    @Override
    public void copyHierAndSplit(ActionData<JSONObject> actionData) {
        String containerModel = actionData.getModel();
        Long containerId = actionData.getContainerId();
        String parentId = actionData.getParentId();
        JSONObject masterInstance = logicInstanceDslService.queryJsonById(containerId);
        List<HierInstance> hierInstanceList = hierInstanceDslService.fetchByParentNodeId(containerModel, containerId, parentId);
        JSONObject dataJson = actionData.getData().get(0);
        JSONObject targetJson = dataJson.getJSONObject("target");
        String targetParentId = targetJson.getString("parentId");
        JSONObject targetValueJson = targetJson.getJSONObject("values");
        List propertyMapList = dataJson.getJSONArray("propertyMapList");
        // 拆分数据依据的字段，如：按照数量拆分
        String splitKey = targetJson.getString("splitKey");
        List<HierInstance> splitResultList = new ArrayList<>();
        hierInstanceList.forEach(hierInstance -> {
            JSONObject valueJson = hierInstance.getValues();
            Integer splitCount = valueJson.getInteger(splitKey);
            if (splitCount == null || splitCount == 0) {
                throw new BusinessException("按" + splitKey + "拆分数量为空或为0");
            }
            for (Integer i = 0; i < splitCount; i++) {
                JSONObject tempTargetValueJson = BeanUtil.copyProperties(targetValueJson, JSONObject.class);
                HierInstance splitHierInstance = BeanUtil.copyProperties(hierInstance, HierInstance.class);
                handleSlavePropertyMap(propertyMapList, masterInstance, JsonUtil.toJSONObject(hierInstance), tempTargetValueJson);
                logicInstanceDslService.handleAutoGenValue(tempTargetValueJson);
                BeanUtil.copyProperties(tempTargetValueJson, valueJson);
                splitHierInstance.setId(null);
                splitHierInstance.setParentId(targetParentId);
                // 处理大小批次号的问题， fetchNumber(${master.values.batch_number})
                if (targetValueJson.containsKey("batch_number")) {
                    String subBatchNumber = fetchStockSubBatchNumber(masterInstance.getJSONObject("values").getString("batch_number"));
                    valueJson.put("batch_number", subBatchNumber);
                }
                splitHierInstance.setValues(BeanUtil.copyProperties(valueJson, JSONObject.class));
                splitResultList.add(splitHierInstance);
            }
        });
        log.info("splitResultList = {}", splitResultList);
        hierInstanceDslService.addBatchChildBySameParent(JsonUtil.transformToJson(splitResultList));
    }

    /**
     * 生成入库小批次号
     *
     * @param batchNumber 大批次号
     * @return
     */
    private String fetchStockSubBatchNumber(String batchNumber) {
        String subBatchNumber = batchNumberDslService.getNextVal(batchNumber);
        String[] subBatchNumberArray = subBatchNumber.split("-");
        subBatchNumber = batchNumber + "-" + StrUtil.padPre(subBatchNumberArray[2], 5, "000000");
        return subBatchNumber;
    }


    /**
     * 处理子表的propertyMap数据
     *
     * @param propertyMapList
     * @param master
     * @param slave
     * @param targetHierValueJson
     */
    private void handleSlavePropertyMap(List<String> propertyMapList, JSONObject master, JSONObject slave, JSONObject targetHierValueJson) {
        if (CollectionUtil.isEmpty(propertyMapList)) {
            return;
        }
        propertyMapList.forEach(propertyMap -> {
            String[] propertyMapArray = propertyMap.split(":");
            String sourceKey = propertyMapArray[0].trim();
            String targetKey = propertyMapArray[1].trim();
            // {{hier.values.quantity - hier.values.saleOrder_outBoundQuantity + hier.values.return_quantity}}: hier.quantity
            if (targetKey.startsWith("hier.")) {
                Object tempNewValue = handleExpression(master, slave, sourceKey);
                targetKey = targetKey.substring("hier.".length());
                targetHierValueJson.put(targetKey, tempNewValue);
            }
        });
    }

    /**
     * 处理公式数据
     *
     * @param master
     * @param slave
     * @param sourceKey
     * @return
     */
    private Object handleExpression(JSONObject master, JSONObject slave, String sourceKey) {
        String originSourceKey = sourceKey;
        String[] expressionArray = ExpressionUtil.handleExpression(sourceKey);
        Object tempValue = null;
        for (int i = 0; i < expressionArray.length; i++) {
            String expression = expressionArray[i];
            if (expression.startsWith("hier.")) {
                expression = expression.substring("hier.".length());
                tempValue = JsonUtil.get(slave, expression);
            } else if (expression.startsWith("master.")) {
                expression = expression.substring("master.".length());
                tempValue = JsonUtil.get(master, expression);
            } else {
                throw new BusinessException("字段映射错误, 源数据的key = {}", sourceKey);
            }
            tempValue = tempValue == null ? 0 : tempValue;
            if (originSourceKey.contains("${")) {
                sourceKey = sourceKey.replace(expressionArray[i], String.valueOf(tempValue));
                sourceKey = sourceKey.replace("${", "");
                sourceKey = sourceKey.replace("}", "");
            }
            // targetKey = targetKey.substring("hier.".length());
            // targetHierValueJson.put(targetKey, tempNewValue);
        }
        if (originSourceKey.contains("${")) {
            log.info("expression = {}", sourceKey);
            return AviatorEvaluator.execute(sourceKey);
        } else {
            return tempValue;
        }
    }

    /**
     * 处理主表的propertyMap数据
     *
     * @param propertyMap
     * @param master
     * @param sourceValueJson
     * @param firstSlaveValueJson
     * @param targetValueJson
     */
    private void handlePropertyMap(Map<String, String> propertyMap, JSONObject master, JSONObject sourceValueJson, JSONObject firstSlaveValueJson, JSONObject targetValueJson) {
        propertyMap.forEach((sourceKey, targetKey) -> {
            if (!targetKey.startsWith("slave.")) {
                if (sourceKey.startsWith("slave.")) {
                    sourceKey = sourceKey.substring("slave.".length());
                    targetValueJson.put(targetKey, firstSlaveValueJson.get(sourceKey));
                } else if (sourceKey.startsWith("master.")) {
                    sourceKey = sourceKey.substring("master.".length());
                    targetValueJson.put(targetKey, master.get(sourceKey));
                } else {
                    targetValueJson.put(targetKey, sourceValueJson.get(sourceKey));
                }
            }
        });
    }


    /**
     * 处理子表的propertyMap数据
     *
     * @param propertyMapList
     * @param master
     * @param slave
     * @param targetValueJson
     */
    private void handlePropertyMap(List<String> propertyMapList, JSONObject master, JSONObject slave, JSONObject targetValueJson) {
        if (CollectionUtil.isEmpty(propertyMapList)) {
            return;
        }
        propertyMapList.forEach(propertyMap -> {
            String[] propertyMapArray = propertyMap.split(":(?!.*:)");
            String sourceKey = propertyMapArray[0].trim();
            String targetKey = propertyMapArray[1].trim();
            Object tempNewValue = sourceKey;
            if (targetKey.startsWith("master.")) {
                if (sourceKey.startsWith("hier.")) {
                    sourceKey = sourceKey.substring("hier.".length());
                    tempNewValue = JsonUtil.get(slave, sourceKey);
                } else if (sourceKey.startsWith("master.")) {
                    sourceKey = sourceKey.substring("master.".length());
                    tempNewValue = JsonUtil.get(master, sourceKey);
                } else {
                    throw new BusinessException("字段映射错误, 源数据的key = {}", sourceKey);
                }
                targetKey = targetKey.substring("master.".length());
                targetValueJson.put(targetKey, tempNewValue);
            }
        });
    }

    /**
     * 根据指定的实例，复制生成下游单据
     * 可以复制多个hier列表
     *
     * @param actionData
     * @return
     */
    @Override
    public ResultInfo<?> copyMasterAndHierList(ActionData<JSONObject> actionData) {
        String model = actionData.getModel();
        Long containerId = actionData.getInstanceId();
        JSONObject logicInstanceJson = logicInstanceDslService.queryJsonById(containerId);
        JSONObject resultJson = new JSONObject();
        resultJson.put("master", logicInstanceJson);
        JSONObject dataJson = actionData.getData().get(0);
        // 创建主表数据
        JSONObject masterTargetJson = dataJson.getJSONObject("masterTarget");
        List propertyMapList = dataJson.getJSONArray("masterPropertyMapList");
        // 如果子记录为空，说明不需要复制主数据，
        JSONObject master = null;

        // 复制hier数据
        JSONArray copyHierArray = dataJson.getJSONArray("copyHierArray");
        for (int i = 0; i < copyHierArray.size(); i++) {
            JSONObject copyHierJson = copyHierArray.getJSONObject(i);
            String hierValueCondition = copyHierJson.getString("hierValueCondition");
            Boolean supportHierNone = copyHierJson.getBoolean("supportHierNone");
            String hierNoneExceptionMsg = copyHierJson.getString("hierNoneExceptionMsg");
            String parentNodeId = copyHierJson.getString("parentNodeId");
            List<HierInstance> tempSlaveList = hierInstanceDslService.fetchByParentNodeId(model, containerId, parentNodeId);
            tempSlaveList = filterSlaveList(hierValueCondition, tempSlaveList);
            tempSlaveList = this.fetchHierInstance(copyHierJson, tempSlaveList);
            if (supportHierNone != null && !supportHierNone && CollectionUtil.isEmpty(tempSlaveList) && StrUtil.isNotBlank(hierNoneExceptionMsg)) {
                throw new BusinessException(StatusCode.ERROR_DATA_ERROR.getCode(), hierNoneExceptionMsg);
            }

            // 如果子表数据为空，说明不需要增加下游数据
            if (CollectionUtil.isNotEmpty(tempSlaveList)) {
                JSONObject hierTargetJson = copyHierJson.getJSONObject("hierTarget");
                List hierPropertyMapList = copyHierJson.getJSONArray("hierPropertyMapList");
                if (master == null) {
                    List<JSONObject> resultData = copy1(Arrays.asList(resultJson), masterTargetJson, propertyMapList);
                    master = resultData.get(0).getJSONObject("master");
                }
                List<JSONObject> slaveList = createHierList(hierPropertyMapList, hierTargetJson, master, JsonUtil.toJSONArray(tempSlaveList));
            }
        }
        return JsonResult.success();
    }

    private List<HierInstance> fetchHierInstance(JSONObject copyHierJson, List<HierInstance> slaveList) {
        // 二次过滤
        JSONObject queryPointer = copyHierJson.getJSONObject("queryPointer");
        if (queryPointer == null) {
            return slaveList;
        }

        String pointModel = queryPointer.getString("model");
        String className = queryPointer.getString("className");
        String fieldName = queryPointer.getString("fieldName");
        String targetFieldName = queryPointer.getString("targetFieldName");
        String condition = queryPointer.getString("condition");
        for (HierInstance hIns : slaveList) {
            JSONObject values = hIns.getValues();
            String fieldNameValue = values.getString(targetFieldName);
            if (StringUtils.isNotBlank(condition)) {
                condition += " and " + fieldName + " = '" + fieldNameValue + "'";
            } else {
                condition += fieldName + " = '" + fieldNameValue + "'";
            }
        }
        List<JSONObject> jsonObjectList = null;
        switch (pointModel) {
            case "consume":
                jsonObjectList = consumeInstanceDslService.query(condition, className, null);
                break;
            case "resource":
                jsonObjectList = resourceInstanceDslService.query(condition, className, null);
                break;
            case "logic":
                jsonObjectList = logicInstanceDslService.query(condition, className, null);
                break;
            case "Tank":
                jsonObjectList = tankInstanceDslService.query(condition, className, null);
                break;
            default:
                break;
        }

        if (CollectionUtil.isNotEmpty(jsonObjectList)) {
            List<String> fieldNameList = jsonObjectList.stream().map(e -> e.getJSONObject("values").getString(fieldName)).collect(Collectors.toList());
            List<HierInstance> tempSlaveList = slaveList.stream()
                    .filter(sl -> fieldNameList.stream().anyMatch(b -> sl.getValues().getString(targetFieldName).equalsIgnoreCase(b)))
                    .collect(Collectors.toList());

            return tempSlaveList;
        } else {
            return new ArrayList<>();
        }
    }


    /**
     * 根据指定的实例，复制生成下游单据
     *
     * @param actionData
     * @return
     */
    @Override
    public ResultInfo<?> copy(ActionData<JSONObject> actionData) {
        String model = actionData.getModel();
        Long containerId = actionData.getInstanceId();
        String parentNodeId = actionData.getParentId();
        JSONObject dataJson = actionData.getData().get(0);
        String hierValueCondition = dataJson.getString("hierValueCondition");
        Boolean supportHierNone = dataJson.getBoolean("supportHierNone");
        String hierNoneExceptionMsg = dataJson.getString("hierNoneExceptionMsg");

        // 查询主表记录
        JSONObject logicInstanceJson = logicInstanceDslService.queryJsonById(containerId);
        List<HierInstance> slaveList = hierInstanceDslService.fetchByParentNodeId(model, containerId, parentNodeId);

        slaveList = filterSlaveList(hierValueCondition, slaveList);

        if (supportHierNone != null && !supportHierNone && CollectionUtil.isEmpty(slaveList) && StrUtil.isNotBlank(hierNoneExceptionMsg)) {
            throw new BusinessException(StatusCode.ERROR_DATA_ERROR.getCode(), hierNoneExceptionMsg);
        }
        List<JSONObject> resultJsonList = new ArrayList<>();
        // 根据上面的查询可以得出，需要分解成3条新记录，如何创建新的实例呢？ 新的主表记录的model, className, 字段映射关系
        JSONObject resultJson = new JSONObject();
        resultJson.put("master", logicInstanceJson);
        // 如果子表数据为空，说明不需要增加下游数据
        if (CollectionUtil.isNotEmpty(slaveList)) {
            resultJson.put("slave", slaveList);
        }
        resultJsonList.add(resultJson);
        JSONObject targetJson = dataJson.getJSONObject("target");
        List propertyMapList = dataJson.getJSONArray("propertyMapList");
        List<JSONObject> resultData = copy1(resultJsonList, targetJson, propertyMapList);
        return JsonResult.success(resultData);
    }

    /**
     * 过滤子表数据
     *
     * @param hierValueCondition
     * @param slaveList
     * @return
     */
    private List<HierInstance> filterSlaveList(String hierValueCondition, List<HierInstance> slaveList) {
        // 根据子表过滤条件，过虑掉不需要的子表数据，条件： ${values.quantity} == ${values.quantity}
        if (StrUtil.isNotBlank(hierValueCondition) && CollectionUtil.isNotEmpty(slaveList)) {
            slaveList = slaveList.stream().filter(d -> {
                String conditionExpression = JsonUtil.handleCondition(hierValueCondition, JsonUtil.toJSONObject(d));
                boolean conditionResult = false;
                try {
                    conditionResult = (boolean) AviatorEvaluator.execute(conditionExpression);
                } catch (Exception e) {
                    log.error("公式判断结果出错， conditionExpression = {}", conditionExpression);
                }
                return conditionResult;
            }).collect(Collectors.toList());
        }
        return slaveList;
    }


    /**
     * # 入库流程
     * 1. 获取入库单产品列表，挨条处理
     * 2. 事件参数中，指定累加标识字段（accumulateFlag）， 如果累加标识为真，
     * 累加字段（accumulateFieldName) 和 唯一识别码(同一个库，同一个库位，同一material_id)，也要同时指定，
     * 通过唯一识别码找到数据（包括库位上的数据和新提交的数据）后，根据累加字段累加数据后，形成新的数据列表。
     * {
     * "accumulateFlag":true,
     * "accumulateFieldName":"quantity",
     * "uniqueFieldNameList":["warehouseCode","binCode","materialId"]
     * }
     * <p>
     * 3. 保存或更新数据，如果有ID就更新，如果没有，就新增
     *
     * @param sourceList  源数据
     * @param paramJson
     * @param targetJson  目标数据存放路径
     * @param propertyMap
     */
    public void accumulatingAndInsert(List<JSONObject> sourceList, JSONObject paramJson, JSONObject targetJson, Map<String, String> propertyMap) {
        boolean accumulateFlag = paramJson.getBooleanValue("accumulateFlag");
        if (accumulateFlag) {
            String accumulateFieldName = paramJson.getString("accumulateFieldName");
            JSONArray uniqueFieldNameList = paramJson.getJSONArray("uniqueFieldNameList");
            Collection<JSONObject> mergedSourceList = mergedAndAccumulate(sourceList, accumulateFieldName, uniqueFieldNameList);
            // 再合并仓库中已有的数据
            targetJson.getString("model");
            String className = targetJson.getString("className");
            mergedSourceList.forEach(source -> {
            });
            // List<LogicInstance> logicInstanceList = logicInstanceDslService.query(className);

        }
    }

    /**
     * 合并，并按指定字段累加
     *
     * @param sourceList
     * @param accumulateFieldName
     * @param uniqueFieldNameList
     */
    private Collection<JSONObject> mergedAndAccumulate(List<JSONObject> sourceList, String accumulateFieldName, JSONArray uniqueFieldNameList) {
        // 将源数据分组合并
        Map<String, JSONObject> sourceMap = new HashMap();
        sourceList.forEach(d -> {
            String key = fetchGroupKey(d, uniqueFieldNameList);
            if (sourceMap.containsKey(key)) {
                int intValue = sourceMap.get(key).getIntValue(accumulateFieldName);
                intValue += d.getIntValue(accumulateFieldName);
                sourceMap.get(key).put(accumulateFieldName, intValue);
            } else {
                sourceMap.put(key, d);
            }
        });
        // 拿到合并而且按指定字段累加之后的数据列表
        Collection<JSONObject> mergedSourceList = sourceMap.values();
        return mergedSourceList;
    }

    private static String fetchGroupKey(JSONObject dataJson, JSONArray uniqueFieldNameList) {
        return uniqueFieldNameList.stream().map(u -> String.valueOf(dataJson.get(u))).collect(Collectors.joining("#"));
    }

    /**
     * 新增或根据指定字段累加数据
     * 1. 用于新增或更新库存数据
     *
     * @return
     */
    public ResultInfo<?> addOrAccumulate(ActionData<JSONObject> actionData) {
        List<JSONObject> dataJsonList = actionData.getData();
        List<String> uniqueFieldNameList = actionData.getUniqueFieldNameList();
        String accumulateFieldName = actionData.getAccumulateFieldName();
        dataJsonList.forEach(dataJson -> {
            List<JSONObject> instanceJsonList = queryJson(actionData);
            // 取出相同的instance
            Optional<JSONObject> uniqueInstanceOption = instanceJsonList.stream().filter(instanceJson -> {
                boolean flag = false;
                for (int i = 0; i < uniqueFieldNameList.size(); i++) {
                    String d = uniqueFieldNameList.get(i);
                    flag = dataJson.getJSONObject("values").get(d)
                            .equals(instanceJson.getJSONObject("values").get(d));
                    if (!flag) break;
                }
                return flag;
            }).findFirst();
            if (uniqueInstanceOption.isPresent()) {
                // 说明原来的值在数据库中是存在的，需要累加
                JSONObject dbInstanceJson = uniqueInstanceOption.get();
                JSONObject dbValueJson = dbInstanceJson.getJSONObject("values");
                int newAccumulateValue = dbValueJson.getIntValue(accumulateFieldName) + dataJson.getJSONObject("values").getIntValue(accumulateFieldName);
                dbValueJson.put(accumulateFieldName, newAccumulateValue);
                dbInstanceJson.put("values", dbValueJson);
                logicInstanceDslService.updateById(dbInstanceJson);
            } else {
                logicInstanceDslService.add(dataJson);
            }
        });
        return JsonResult.success();
    }

    /**
     * 查询数据并分组求和
     * groupKey可以为多个字段
     *
     * @return
     */
    @Override
    public ResultInfo<?> queryGroupAndSum(ActionData<JSONObject> actionData) {
        String condition = actionData.getCondition();
        String className = actionData.getClassName();
        List<String> groupByList = actionData.getGroupByList();
        String sumKey = actionData.getSumKey();
        String orderBy = actionData.getOrderBy();
        List<JSONObject> resultList = logicInstanceDslService.queryGroupAndSum(condition, className, groupByList, sumKey, orderBy);
        return JsonResult.success(resultList);
    }

    /**
     * 通用方法，查询结果为Josn数据
     *
     * @param actionData
     * @return
     */
    @Override
    public List<JSONObject> queryJson(ActionData<JSONObject> actionData) {
        String condition = actionData.getCondition();
        String className = actionData.getClassName();
        String orderBy = actionData.getOrderBy();
        String hierValueCondition = actionData.getHierValueCondition();
        List<JSONObject> queryJsonList = logicInstanceDslService.query(condition, className, orderBy, hierValueCondition);
        return queryJsonList;
    }

    @Override
    public ResultInfo<List<JSONObject>> queryByIds(ActionData<JSONObject> actionData) {
        List<Long> ids = actionData.getIds();
        List<JSONObject> resultList = logicInstanceDslService.queryByIds(ids);
        return JsonResult.success(resultList);
    }

    /**
     * 对查询条件进行过滤
     * 在过滤时，可以指定过滤的条件，以及分组字段，同一组数据，不会被过滤掉
     *
     * @param actionData
     * @return
     */
    @Override
    public ResultInfo<List<JSONObject>> queryByFilter(ActionData<JSONObject> actionData) {
        String groupKey = actionData.getGroupKey();
        String filter = actionData.getFilter();
        List<JSONObject> instanceJsonList = queryJson(actionData);
        List<JSONObject> resultList = filterResult(groupKey, filter, instanceJsonList);
        return JsonResult.success(resultList);
    }

    /**
     * 过滤查询结果
     *
     * @param groupKey         分组标识，同一组数据不会被过滤掉
     * @param filter           过滤条件，是个带公式的表达式， 如：sum(quantity)>=50
     * @param instanceJsonList
     * @return
     */
    private List<JSONObject> filterResult(String groupKey, String filter, List<JSONObject> instanceJsonList) {
        if (StrUtil.isBlank(filter)) {
            return instanceJsonList;
        }
        String filterCondition = filter.split("\\)")[1];
        List<JSONObject> resultList = new ArrayList<>();
        // sum(quantity)>=50
        Pattern pattern = Pattern.compile("(?<=sum\\().*?(?=\\))");
        Matcher matcher = pattern.matcher(filter);
        if (matcher.find()) {
            Object filterGroupByValue = null;
            boolean filterGroupResult = false;
            int sumFiledValue = 0;
            // 获取括号中的内容，如：quantity
            String sumField = matcher.group();
            for (int i = 0; i < instanceJsonList.size(); i++) {
                JSONObject instanceJson = instanceJsonList.get(i);
                // 第一条先初始化，防止第一条就满足记录，后面的同一组数据无法添加到结果中
                if (i == 0) {
                    filterGroupByValue = instanceJson.getJSONObject("values").get(groupKey);
                }
                if (filterGroupResult == true) {
                    // 如果符合条件，判断是否为一组数据
                    if (StrUtil.isNotBlank(groupKey)) {
                        Object tempFilterGroupByValue = instanceJson.getJSONObject("values").get(groupKey);
                        if (!tempFilterGroupByValue.equals(filterGroupByValue)) {
                            break;
                        } else {
                            resultList.add(instanceJson);
                            // filterGroupByValue = tempFilterGroupByValue;
                        }
                    } else {
                        break;
                    }
                } else {
                    resultList.add(instanceJson);
                    sumFiledValue += instanceJson.getJSONObject("values").getIntValue(sumField);
                    filterGroupResult = (boolean) AviatorEvaluator.execute(sumFiledValue + filterCondition);
                    // 如果不满足退出指定的条件，更新分组判断标识为最新的值
                    filterGroupByValue = instanceJson.getJSONObject("values").get(groupKey);
                }
            }
        }
        return resultList;
    }

    /**
     * 根据指定字段扣减数据
     * 1. 用于扣减库存数据
     *
     * @return
     */
    @Override
    public ResultInfo<?> deduct(ActionData<JSONObject> actionData) {
        // 记录具体扣减的记录
        List<JSONObject> updateDataList = new ArrayList<>();
        // 记录扣减明细
        List<JSONObject> addDataList = new ArrayList<>();
        List<JSONObject> dataJsonList = actionData.getData();
        List<String> uniqueFieldNameList = actionData.getUniqueFieldNameList();
        // 扣减明细中，需要被覆盖的新字段名称
        List<String> coverFieldNameList = actionData.getCoverFieldNameList();
        // 实际数据中要扣减的字段名，如：出库时，修改的是available_quantity字段的值
        String deductFieldName = actionData.getDeductFieldName();
        // data中要扣减的字段名，如：出库时，指定出库数量的字段为quantity
        String dataDeductFieldName = actionData.getDataDeductFieldName();
        // 根据条件，查询出明细数量，如：库存明细数量
        List<JSONObject> instanceJsonList = queryJson(actionData);
        // 根据指定字段，确定可以操作的记录
        dataJsonList.forEach(dataJson -> {
            // 取出可以操作的记录，如：取出可以出库的明细，操作顺序由查询条件确定
            List<JSONObject> availableList = instanceJsonList.stream().filter(instanceJson -> {
                boolean flag = false;
                for (int i = 0; i < uniqueFieldNameList.size(); i++) {
                    String d = uniqueFieldNameList.get(i);
                    flag = dataJson.getJSONObject("values").get(d)
                            .equals(instanceJson.getJSONObject("values").get(d));
                    if (!flag) break;
                }
                return flag;
            }).collect(Collectors.toList());
            // 扣减库存，如：出库时，修改的是available_quantity字段的值
            int availableQuantity = availableList.stream().map(d -> d.getJSONObject("values").getIntValue(deductFieldName))
                    .mapToInt(d -> d).sum();
            // 需要扣减的库存，如：出库时，指定出库数量的字段为quantity
            int dataDeductQuantity = dataJson.getJSONObject("values").getIntValue(dataDeductFieldName);
            if (availableQuantity >= dataDeductQuantity) {
                // 开始按顺序扣减
                for (int i = 0; i < availableList.size(); i++) {
                    JSONObject availableJson = availableList.get(i);
                    JSONObject avaliableValueJson = availableJson.getJSONObject("values");
                    int originQuantity = avaliableValueJson.getIntValue(deductFieldName);
                    if (dataDeductQuantity <= originQuantity) {
                        // 如果当前记录足够扣减，直接扣减
                        avaliableValueJson.put(deductFieldName, originQuantity - dataDeductQuantity);
                        updateDataList.add(availableJson);

                        // 创建变更明细记录
                        // JSONObject addJson = BeanUtil.copyProperties(availableJson, JSONObject.class);
                        JSONObject addJson = ObjectUtil.cloneByStream(availableJson);
                        addJson.remove("id");
                        addJson.remove("locked");
                        addJson.getJSONObject("values").put(deductFieldName, 0);
                        addJson.getJSONObject("values").put(dataDeductFieldName, -dataDeductQuantity);
                        coverFieldNameList.forEach(d -> {
                            addJson.getJSONObject("values").put(d, dataJson.getJSONObject("values").get(d));
                        });
                        addDataList.add(addJson);
                        break;
                    } else {
                        // 不够扣减，将当前记录扣减为0，然后接着扣减
                        avaliableValueJson.put(deductFieldName, 0);
                        dataDeductQuantity = dataDeductQuantity - originQuantity;
                        updateDataList.add(availableJson);

                        // 创建变更明细记录
                        // JSONObject addJson = BeanUtil.copyProperties(availableJson, JSONObject.class);
                        JSONObject addJson = ObjectUtil.cloneByStream(availableJson);
                        addJson.remove("id");
                        addJson.remove("locked");
                        addJson.getJSONObject("values").put(deductFieldName, 0);
                        addJson.getJSONObject("values").put(dataDeductFieldName, -originQuantity);
                        coverFieldNameList.forEach(d -> {
                            addJson.getJSONObject("values").put(d, dataJson.getJSONObject("values").get(d));
                        });
                        addDataList.add(addJson);
                    }
                }
            } else {
                throw new BusinessException("扣减数量不足");
            }
        });

        log.info("addDataList = {}", addDataList);
        log.info("updateDataList = {}", updateDataList);
        List<JSONObject> resultList = ObjectUtil.cloneByStream(addDataList);
        logicInstanceDslService.updateByIds(updateDataList);
        logicInstanceDslService.batchAdd(addDataList);

        // 更新主表库存数据，需要指定能唯一确定一条记录的字段，
        // List<JSONObject> resultList = addDataList.stream().map(d -> d.getJSONObject("values")).collect(Collectors.toList());
        return JsonResult.success(resultList);
    }

    /**
     * 根据明细数据，更新主数据，业务如下：
     * 1. 根据库存扣减明细，去更新库存数量
     *
     * @return
     */
    // @Override
    public ResultInfo<?> batchUpdateByDetail(ActionData<JSONObject> actionData) {
        log.info("actionData = {}", actionData);
        String className = actionData.getClassName();
        List<String> uniqueFieldNameList = actionData.getUniqueFieldNameList();
        String dataDeductFieldName = actionData.getDataDeductFieldName();
        List<JSONObject> dataList = actionData.getData();

        for (int i = 0; i < dataList.size(); i++) {
            String condition = "";
            JSONObject valueJson = dataList.get(i);
            // JSONObject valueJson = dataJson.getJSONObject("values");
            for (int j = 0; j < uniqueFieldNameList.size(); j++) {
                if (j > 0) {
                    condition += " and ";
                }
                String uniqueFieldName = uniqueFieldNameList.get(j);
                Object value = valueJson.getJSONObject("values").get(uniqueFieldName);
                if (value instanceof Number) {
                    condition += uniqueFieldName + "=" + value;
                } else {
                    condition += uniqueFieldName + "='" + value + "'";
                }
            }
            JSONObject newDataJson = new JSONObject();
            JSONObject newValueJson = new JSONObject();
            newValueJson.put(dataDeductFieldName, valueJson.getJSONObject("values").getLongValue(dataDeductFieldName));
            newDataJson.put("values", newValueJson);
            logicInstanceDslService.deductByCondition(className, condition, dataDeductFieldName, newValueJson);
        }
        return JsonResult.success();
    }

    /**
     * 根据子数据，更新主数据，支持公式
     * values:{
     * "status":1,
     * "quantity":sum(${quantity})
     * }
     *
     * @param actionData
     * @return
     */
    @Override
    public ResultInfo<?> updateMasterByHier(ActionData<JSONObject> actionData) {
        JSONObject data = actionData.getData().get(0);
        Long containerId = data.getLong("id");
        String className = data.getString("className");
        String parentId = data.getString("parentId");
        JSONObject valueJson = data.getJSONObject("values");
        // List<HierInstance> hierInstanceList = hierInstanceDslService.queryByContainerId(ModelType.Logic.getCode(), instanceId);
        List<HierInstance> hierInstanceList = hierInstanceDslService.queryChildByContainerId(ModelType.Logic.getCode(), className, containerId, parentId, null);
        valueJson.forEach((k, v) -> {
            String strV = String.valueOf(v);
            if (strV.startsWith("sum(")) {
                String outExpression = ExpressionUtil.fetchByReg(strV, "\\((.*?)\\)");
                if (StrUtil.isNotBlank(outExpression)) {
                    if (outExpression.startsWith("${")) {
                        // String sumExpression = ExpressionUtil.fetchByReg(outExpression, "\\$\\{(.*?)\\}");
                        BigDecimal sumResult = hierInstanceList.stream().map(d -> {
                            Object tempResult = ExpressionUtil.handleExpression(JsonUtil.toJSONObject(d), outExpression);
                            BigDecimal sumValue = new BigDecimal(String.valueOf(tempResult));
                            return sumValue;
                        }).reduce(BigDecimal.ZERO, BigDecimal::add);
                        sumResult = sumResult.setScale(9, BigDecimal.ROUND_HALF_UP);
                        valueJson.put(k, sumResult);
                    }
                }
            }
        });
        return updateById(actionData);
    }
}
